const {parseString} = require('xml2js')
const Base = require('./base')
const WXBizMsgCrypt = require('wechat-crypto')
const ejs = require('ejs')
const tpl = ['<xml>',
  '<ToUserName><![CDATA[<%-toUsername%>]]></ToUserName>',
  '<FromUserName><![CDATA[<%-fromUsername%>]]></FromUserName>',
  '<CreateTime><%=createTime%></CreateTime>',
  '<% if (msgType === "device_event" && (Event === "subscribe_status" || Event === "unsubscribe_status")) { %>',
  '<% if (Event === "subscribe_status" || Event === "unsubscribe_status") { %>',
  '<MsgType><![CDATA[device_status]]></MsgType>',
  '<DeviceStatus><%=DeviceStatus%></DeviceStatus>',
  '<% } else { %>',
  '<MsgType><![CDATA[<%=msgType%>]]></MsgType>',
  '<Event><![CDATA[<%-Event%>]]></Event>',
  '<% } %>',
  '<% } else { %>',
  '<MsgType><![CDATA[<%=msgType%>]]></MsgType>',
  '<% } %>',
  '<% if (msgType === "news") { %>',
  '<ArticleCount><%=content.length%></ArticleCount>',
  '<Articles>',
  '<% content.forEach(function(item){ %>',
  '<item>',
  '<Title><![CDATA[<%-item.title%>]]></Title>',
  '<Description><![CDATA[<%-item.description%>]]></Description>',
  '<PicUrl><![CDATA[<%-item.picUrl || item.picurl || item.pic %>]]></PicUrl>',
  '<Url><![CDATA[<%-item.url%>]]></Url>',
  '</item>',
  '<% }); %>',
  '</Articles>',
  '<% } else if (msgType === "music") { %>',
  '<Music>',
  '<Title><![CDATA[<%-content.title%>]]></Title>',
  '<Description><![CDATA[<%-content.description%>]]></Description>',
  '<MusicUrl><![CDATA[<%-content.musicUrl || content.url %>]]></MusicUrl>',
  '<HQMusicUrl><![CDATA[<%-content.hqMusicUrl || content.hqUrl %>]]></HQMusicUrl>',
  '<% if (content.thumbMediaId) { %> ',
  '<ThumbMediaId><![CDATA[<%-content.thumbMediaId || content.mediaId %>]]></ThumbMediaId>',
  '<% } %>',
  '</Music>',
  '<% } else if (msgType === "voice") { %>',
  '<Voice>',
  '<MediaId><![CDATA[<%-content.mediaId%>]]></MediaId>',
  '</Voice>',
  '<% } else if (msgType === "image") { %>',
  '<Image>',
  '<MediaId><![CDATA[<%-content.mediaId%>]]></MediaId>',
  '</Image>',
  '<% } else if (msgType === "video") { %>',
  '<Video>',
  '<MediaId><![CDATA[<%-content.mediaId%>]]></MediaId>',
  '<Title><![CDATA[<%-content.title%>]]></Title>',
  '<Description><![CDATA[<%-content.description%>]]></Description>',
  '</Video>',
  '<% } else if (msgType === "hardware") { %>',
  '<HardWare>',
  '<MessageView><![CDATA[<%-HardWare.MessageView%>]]></MessageView>',
  '<MessageAction><![CDATA[<%-HardWare.MessageAction%>]]></MessageAction>',
  '</HardWare>',
  '<FuncFlag>0</FuncFlag>',
  '<% } else if (msgType === "device_text" || msgType === "device_event") { %>',
  '<DeviceType><![CDATA[<%-DeviceType%>]]></DeviceType>',
  '<DeviceID><![CDATA[<%-DeviceID%>]]></DeviceID>',
  '<% if (msgType === "device_text") { %>',
  '<Content><![CDATA[<%-content%>]]></Content>',
  '<% } else if ((msgType === "device_event" && Event != "subscribe_status" && Event != "unsubscribe_status")) { %>',
  '<Content><![CDATA[<%-content%>]]></Content>',
  '<Event><![CDATA[<%-Event%>]]></Event>',
  '<% } %>',
  '<SessionID><%=SessionID%></SessionID>',
  '<% } else if (msgType === "transfer_customer_service") { %>',
  '<% if (content && content.kfAccount) { %>',
  '<TransInfo>',
  '<KfAccount><![CDATA[<%-content.kfAccount%>]]></KfAccount>',
  '</TransInfo>',
  '<% } %>',
  '<% } else { %>',
  '<Content><![CDATA[<%-content%>]]></Content>',
  '<% } %>',
  '</xml>'].join('')
const compiled = ejs.compile(tpl)
/*!
 * 将内容回复给微信的封装方法
 */
const reply = function (content, fromUsername, toUsername, message) {
  var info = {}
  var type = 'text'
  info.content = content || ''
  info.createTime = new Date().getTime()
  if (message && (message.MsgType === 'device_text' || message.MsgType === 'device_event')) {
    info.DeviceType = message.DeviceType
    info.DeviceID = message.DeviceID
    info.SessionID = isNaN(message.SessionID) ? 0 : message.SessionID
    info.createTime = Math.floor(info.createTime / 1000)
    if (message['Event'] === 'subscribe_status' || message['Event'] === 'unsubscribe_status') {
      delete info.content
      info.DeviceStatus = isNaN(content) ? 0 : content
    } else {
      if (!(content instanceof Buffer)) {
        content = String(content)
      }
      info.content = new Buffer(content).toString('base64')
    }
    type = message.MsgType
    if (message.MsgType === 'device_event') {
      info['Event'] = message['Event']
    }
  } else if (Array.isArray(content)) {
    type = 'news'
  } else if (typeof content === 'object') {
    if (content.hasOwnProperty('type')) {
      type = content.type
      if (content.content) {
        info.content = content.content
      }
      if (content.HardWare) {
        info.HardWare = content.HardWare
      }
    } else {
      type = 'music'
    }
  }
  info.msgType = type
  info.toUsername = toUsername
  info.fromUsername = fromUsername
  yy.log.info(compiled(info))
  return compiled(info)
}

const reply2CustomerService = function (fromUsername, toUsername, kfAccount) {
  var info = {}
  info.msgType = 'transfer_customer_service'
  info.createTime = new Date().getTime()
  info.toUsername = toUsername
  info.fromUsername = fromUsername
  info.content = {}
  if (typeof kfAccount === 'string') {
    info.content.kfAccount = kfAccount
  }
  return compiled(info)
}

const wrapTpl = '<xml>' +
    '<Encrypt><![CDATA[<%-encrypt%>]]></Encrypt>' +
    '<MsgSignature><![CDATA[<%-signature%>]]></MsgSignature>' +
    '<TimeStamp><%-timestamp%></TimeStamp>' +
    '<Nonce><![CDATA[<%-nonce%>]]></Nonce>' +
    '</xml>'

const encryptWrap = ejs.compile(wrapTpl)
module.exports = class extends Base {
  constructor (...arg) {
    super(...arg)
    this.cryptor = new WXBizMsgCrypt(this.conf.msg_token, this.conf.msg_encode, this.conf.appid)
  }
  async getPost (d) {
    if (d.Encrypt) {
      const {message} = this.cryptor.decrypt(d.Encrypt)
      d = await this.xmlformat(message)
    }
    this.message = d
    return d
  }
  reply (content) {
    const message = this.message
    return this.encryptXml(reply(content, message.ToUserName, message.FromUserName, message))
  }
  transfer2CustomerService (kfAccount) {
    const message = this.message
    return this.encryptXml(reply2CustomerService(message.ToUserName, message.FromUserName, kfAccount))
  };
  encryptXml (xml) {
    this.getData = this.getData || {}
    if (!this.getData.encrypt_type || this.getData.encrypt_type === 'raw') {
      return xml
    } else {
      var wrap = {}
      wrap.encrypt = this.cryptor.encrypt(xml)
      wrap.nonce = parseInt((Math.random() * 100000000000), 10)
      wrap.timestamp = new Date().getTime()
      wrap.signature = this.cryptor.getSignature(wrap.timestamp, wrap.nonce, wrap.encrypt)
      return encryptWrap(wrap)
    }
  }
}
